﻿using System;
using System.Collections.Concurrent;
using System.Windows.Forms;
using ACSR.SSMS.Core;
using EnvDTE;
using EnvDTE80;
using MEFAddin.Controllers;
using MEFAddin.Interfaces;

namespace MEFAddin.Adapters
{
    public class WindowAdapter : MEFAddin.Adapters.IWindowAdapter
    {
        private AddInContext _AddInContext;

        private ConcurrentDictionary<object, IToolWindowContext> _windows;

        private readonly string customControlHostingWindowTypeName = "ACSR.SqlServer.Addin.Core.UI.UcControlHost";

        /// <summary>
        /// Initializes a new instance of the <see cref="WindowAdapter"/> class.
        /// </summary>
        /// <param name="addinContext">The addin context.</param>
        public WindowAdapter(AddInContext addinContext)
        {
            this._AddInContext = addinContext;
            _windows = new ConcurrentDictionary<object, IToolWindowContext>();
        }

        /// <summary>
        /// Gets the common UI assembly location.
        /// </summary>
        public string CommonUIAssemblyLocation
        {
            get
            {
                return this._AddInContext.UIDll;
            }
        }

        /// <summary>
        /// Gets the windows.
        /// </summary>
        public Windows Windows
        {
            get
            {
                return _AddInContext.AddInInstance.DTE.Windows;
            }
        }

        /// <summary>
        /// Gets the active window.
        /// </summary>
        public Window ActiveWindow
        {
            get
            {
                return _AddInContext.AddInInstance.DTE.ActiveWindow;
            }
        }

        /// <summary>
        /// Determines whether [is text window] [the specified window].
        /// </summary>
        /// <param name="window">The window.</param>
        /// <returns>
        ///   <c>true</c> if [is text window] [the specified window]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsTextWindow(Window window)
        {
            return (window != null && window.Selection != null && (window.Caption != "SQL Navigator"));
        }

        /// <summary>
        /// Finds the or create host window.
        /// </summary>
        /// <param name="controlToHost">The control to host.</param>
        /// <param name="caption">The caption.</param>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public IToolWindowContext FindOrCreateHostWindow(Control controlToHost, string caption, string guid)
        {
            IToolWindowContext window = FindWindow(customControlHostingWindowTypeName, caption);
            if (window == null)
            {
                return CreateHostWindow(controlToHost, caption, guid);
            }

            return window;
        }

        /// <summary>
        /// Creates the host window.
        /// </summary>
        /// <param name="controlToHost">The control to host.</param>
        /// <param name="caption">The caption.</param>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public IToolWindowContext CreateHostWindow(Control controlToHost, string caption, string guid)
        {
            controlToHost.Dock = System.Windows.Forms.DockStyle.Fill;
            controlToHost.Visible = true;
            var window = CreateCommonUIControl(customControlHostingWindowTypeName, caption, new Guid(guid));
            HostWindow(((dynamic)window.ControlObject), controlToHost);
            return window;
        }

        /// <summary>
        /// Hosts the window.
        /// </summary>
        /// <param name="hostWindow">The host window.</param>
        /// <param name="controlToHost">The control to host.</param>
        public void HostWindow(dynamic hostWindow, Control controlToHost)
        {
            hostWindow.HostChildControl(new ControlContext(controlToHost));
        }

        /// <summary>
        /// Creates the common UI control.
        /// </summary>
        /// <param name="typeName">Name of the type.</param>
        /// <param name="caption">The caption.</param>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public IToolWindowContext CreateCommonUIControl(string typeName, string caption, Guid guid)
        {
            return CreateToolWindow(this._AddInContext.UIDll, typeName, caption, guid);
        }

        /// <summary>
        /// Creates the tool window.
        /// </summary>
        /// <param name="assemblyLocation">The assembly location.</param>
        /// <param name="typeName">Name of the type.</param>
        /// <param name="Caption">The caption.</param>
        /// <param name="uiTypeGuid">The UI type GUID.</param>
        /// <returns></returns>
        public IToolWindowContext CreateToolWindow(string assemblyLocation, string typeName, string Caption, Guid uiTypeGuid)
        {
            Windows2 win2 = _AddInContext.ApplicationObject.Windows as Windows2;
            if (win2 != null)
            {
                object controlObject = null;

                Window toolWindow = win2.CreateToolWindow2(this._AddInContext.AddInInstance, assemblyLocation, typeName, Caption, "{" + uiTypeGuid.ToString() + "}", ref controlObject);
                Window2 toolWindow2 = (Window2)toolWindow;
                toolWindow.Linkable = false;
                //toolWindow.IsFloating = true;
                try
                {
                    toolWindow.WindowState = vsWindowState.vsWindowStateMaximize;
                }
                catch
                {
                }

                toolWindow.Visible = true;

                var ctx = new ToolWindowContext(toolWindow, toolWindow2, controlObject);
                this._windows[new { typeName, Caption }] = ctx;
                return ctx;
            }

            return null;
        }

        /// <summary>
        /// Finds the window.
        /// </summary>
        /// <param name="typeName">Name of the type.</param>
        /// <param name="Caption">The caption.</param>
        /// <returns></returns>
        public IToolWindowContext FindWindow(string typeName, string Caption)
        {
            IToolWindowContext window = null;
            if (!this._windows.TryGetValue(new { typeName, Caption }, out window))
            {
                return window;
            }

            return null;
        }

        /// <summary>
        /// Finds the or create tool window.
        /// </summary>
        /// <param name="typeName">Name of the type.</param>
        /// <param name="Caption">The caption.</param>
        /// <param name="uiTypeGuid">The UI type GUID.</param>
        /// <returns></returns>
        public IToolWindowContext FindOrCreateToolWindow(string typeName, string Caption, Guid uiTypeGuid)
        {
            IToolWindowContext window = FindWindow(typeName, Caption);
            if (window == null)
            {
                return CreateToolWindow(this._AddInContext.UIDll, typeName, Caption, uiTypeGuid);
            }

            return window;
        }

        /// <summary>
        /// Finds the or create log window.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public IToolWindowContext FindOrCreateLogWindow(string name)
        {
            return FindOrCreateToolWindow("ACSR.SqlServer.Addin.Core.UI.UcLogWindow", "ACSR Log", new Guid("3ADC13FF-DCF4-4C49-B2EF-3D78DECDC664"));
        }

        /// <summary>
        /// Creates the log window.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public IToolWindowContext CreateLogWindow(string name)
        {
            return CreateToolWindow(this._AddInContext.UIDll, "ACSR.SqlServer.Addin.Core.UI.UcLogWindow", "ACSR Log", new Guid("3ADC13FF-DCF4-4C49-B2EF-3D78DECDC664"));
        }
    }
}
